


namespace Orz.LogManager
{
	//========================================================================
	// 	Imported Namespaces
	//========================================================================

	using System;
	using System.IO;
	using System.Collections;
	using System.Text.RegularExpressions;
	using System.Diagnostics;
	using System.Windows.Forms;
	using Orz.LogManager.Config;
	
	
		
	///
	/// <summary>
	/// Utility class containing functions for handling files and filenames.
	/// </summary>
	/// <remarks>
	/// This class contains methods that help with finding files, using wildcards
	/// and dates as necessary.
	/// </remarks>
	///
	public class FileFinder
	{
		//================================================================
		// 	Methods
		//================================================================

		///
		/// <summary>
		/// Inserts date values in the given path.
		/// </summary>
		///
		public static String ConvertToUnix (string sFile_p)
		{
			if (null == sFile_p  ||  0 == sFile_p.Length) return sFile_p;
			
			return ConvertDates (sFile_p);			
		}
		
		
		
		
		///
		/// <summary>
		/// Inserts date values and searches for a file on the local Windows
		/// file system that matches the path.  The chosen match must also match 
		/// sAdditionalRegexMatch_p, unless that parameter is null or blank.
		/// </summary>
		///
		public static String FindFile (String sFile_p, String sAdditionalRegexMatch_p, multipleFileMatchStrategyType strategy_p)
		{				
			if (null == sFile_p  ||  0 == sFile_p.Length) return sFile_p;
			
			sFile_p = ConvertDates(sFile_p);
			
			String sBuildPath = "";		
			String[] vsParts = sFile_p.Split('\\');
			
			foreach (String sPart in vsParts)
			{			
				if (sPart.Length > 0)
				{
					if (sPart.IndexOf("*") >= 0)
					{
						String sMatch = FindMatch (Directory.GetFiles(sBuildPath), sPart, sAdditionalRegexMatch_p, strategy_p);
						
						if (null == sMatch)
						{
							sMatch = FindMatch (Directory.GetDirectories(sBuildPath), sPart, sAdditionalRegexMatch_p, strategy_p);												
						}									
						
						sBuildPath = sMatch + "\\";
					}
					else
					{
						sBuildPath += sPart + "\\";
					}
				}
				else
				{
					sBuildPath += sPart + "\\";
				}
			}
			
			sBuildPath = sBuildPath.Remove(sBuildPath.Length - 1, 1);				
			
			return sBuildPath;
		}
		
		
		
		
		///
		/// <summary>
		/// Searches through the given array of paths to find the most recent one that matches <code>sWildcardedName_p</code>
		/// (or null if no match is found).  The chosen match must also match sAdditionalRegexMatch_p, unless that parameter
		/// is null or blank.
		/// </summary>
		///
		private static String FindMatch(String[] vsPossibles_p, String sWildcardedName_p, String sAdditionalRegexMatch_p, multipleFileMatchStrategyType strategy_p)
		{
			String sFirstMatch = null;
			String sLastMatch = null;
			String sMostRecentMatch = null;
			DateTime mostRecentMatchTimestamp = DateTime.Now;
			
			
			sWildcardedName_p = "\\\\" + ConvertFisherPriceWildcards (sWildcardedName_p) + "$";						
			
			foreach (String sPossibleMatch in vsPossibles_p)
			{
				Log.Debug("Checking for a match with pattern [" + sWildcardedName_p + "] and file [" + sPossibleMatch + "]");
				
				if (Regex.IsMatch(sPossibleMatch, sWildcardedName_p, RegexOptions.IgnoreCase))
				{
					if (null != sAdditionalRegexMatch_p  &&  sAdditionalRegexMatch_p.Length > 0)
					{
						if (! Regex.IsMatch(sPossibleMatch, sAdditionalRegexMatch_p, RegexOptions.IgnoreCase))
						{
							continue;
						}
					}
					
					if (null == sFirstMatch)
					{
						sFirstMatch = sPossibleMatch;
					}
					
					sLastMatch = sPossibleMatch;
					
					DateTime possibleMatchTimestamp = File.GetLastWriteTime(sPossibleMatch);
					
					if (null == sMostRecentMatch)
					{
						Log.Debug("Found the first match.  Timestamp is " + possibleMatchTimestamp);
						sMostRecentMatch = sPossibleMatch;
						mostRecentMatchTimestamp = possibleMatchTimestamp;
					}
					else 
					{
						// Compare the timestamps						
						Log.Debug("Found a subsequent match - timestamp is " + possibleMatchTimestamp);
						
						if (possibleMatchTimestamp.CompareTo(mostRecentMatchTimestamp) > 0)
						{
							Log.Debug("This file is more recent");
							sMostRecentMatch = sPossibleMatch;
							mostRecentMatchTimestamp = possibleMatchTimestamp;
						}
					}					
				}
			}
			
			String sFinalMatch;
			
			if (multipleFileMatchStrategyType.chooseFirst == strategy_p)
			{
				sFinalMatch = sFirstMatch;
			}
			else if (multipleFileMatchStrategyType.chooseLast == strategy_p)
			{
				sFinalMatch = sLastMatch;
			}
			else
			{
				sFinalMatch = sMostRecentMatch;
			}
			
			Log.Debug("Final match [" + sFinalMatch + "]");
			
			return sFinalMatch;
		}
		
		
		
		
		///
		/// <summary>
		/// Replaces play-school 'one*' style wildcards with real-man regexp ones (i.e. 'one.*').  Grr.
		/// </summary>
		///
		private static String ConvertFisherPriceWildcards(String sOriginal_p)
		{
			return Regex.Replace(sOriginal_p, "\\*", ".*");
		}
		
		
		
		
		///
		/// <summary>
		/// Searches for date placeholders in the path and replaces them with current date values.
		/// </summary>
		/// <remarks>
		/// The following substitutions are made:
		/// <list type="bullet">
		///	<listheader>
		///		<term>Placeholder</term>
		///		<description>Substitution</description>
		///	</listheader>
		///	<item>
		///		<term>%Y</term>
		///		<description>Converted to the four-digit year e.g. '2003'</description>
		///	</item>
		///	<item>
		///		<term>%y</term>
		///		<description>Converted to the two-digit year e.g. '03'</description>
		///	</item>
		///	<item>
		///		<term>%d</term>
		///		<description>Converted to the two-digit day e.g. '31'</description>
		///	</item>
		///	<item>
		///		<term>%m</term>
		///		<description>Converted to the two-digit month e.g. '09'</description>
		///	</item>
		/// </list>
		/// </remarks>
		///
		private static String ConvertDates (String sFile_p)
		{
			int iCentury = DateTime.Now.Year % 100;
			String sCentury = (iCentury < 10 ? "0" : "") + iCentury.ToString();
			String sMonth = (DateTime.Now.Month < 10 ? "0" : "") + DateTime.Now.Month.ToString();
			String sDay = (DateTime.Now.Day < 10 ? "0" : "") + DateTime.Now.Day.ToString();
					
			sFile_p = sFile_p.Replace("%Y", DateTime.Now.Year.ToString());
			sFile_p = sFile_p.Replace("%y", sCentury);
			sFile_p = sFile_p.Replace("%d", sDay);
			sFile_p = sFile_p.Replace("%m", sMonth);		
			return sFile_p;
		}
		
		
		
	} // end class
}
	
